package com.jeomo.common.quartz.provider.web.controller;

import com.jeomo.common.core.dto.PageQueryDto;
import com.jeomo.common.core.dto.PageResponseDto;
import com.jeomo.common.core.request.PageRequest;
import com.jeomo.common.core.result.CommonResult;
import com.jeomo.common.core.util.BeanCopyUtil;
import com.jeomo.common.core.util.StringUtils;
import com.jeomo.common.core.vo.PageResponseVo;
import com.jeomo.common.quartz.provider.config.CronUtil;
import com.jeomo.common.quartz.provider.web.request.JobRequest;
import com.jeomo.common.quartz.provider.web.vo.JobVO;
import com.jeomo.common.quartz.starter.entity.JobParameter;
import com.jeomo.common.quartz.starter.service.BaseJob;
import com.jeomo.common.quartz.starter.service.IJobAndTriggerService;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.Date;

/**
 * <h3>springboot-quartz</h3>
 * <p>controller</p>
 *
 * @author : 崔贺
 * @date : 2020-08-18 16:17
 **/
@RestController
@RequestMapping("/quartz")
public class JobController {

    @Resource
    private IJobAndTriggerService iJobAndTriggerService;
    @Resource
    private Scheduler scheduler;

    private static Logger log = LoggerFactory.getLogger(JobController.class);

    /**
     * @param jobRequest
     * @description:
     * @return: com.jeomo.common.core.result.CommonResult<java.lang.String>
     * @author: 崔贺
     * @time: 2020/12/8 14:31
     */
    @PostMapping("/addJob")
    public CommonResult<String> addJob(@RequestBody JobRequest jobRequest) throws Exception {
        String jobName = jobRequest.getJobName();
        String jobClassName = jobRequest.getJobClassName();
        String jobGroupName = jobRequest.getJobGroupName();
        Date jobDate = jobRequest.getJobDate();
        String cronExpression;
        Trigger trigger;

        if (StringUtils.isEmpty(jobClassName) || StringUtils.isEmpty(jobGroupName)) {
            return CommonResult.failure("参数为空");
        }
        // 是否立即执行
        if (jobRequest.getImmediately()) {
            trigger = TriggerBuilder.newTrigger()
                    .withIdentity(jobClassName, jobGroupName)
                    .withSchedule(SimpleScheduleBuilder.simpleSchedule()).startNow().build();
        } else {
            //表达式为空时间不为空说明  要指定时间执行
            if (jobDate != null) {
                //将指定的时间转换成corn表达式
                cronExpression = CronUtil.getCron(jobDate);
            } else {
                cronExpression = jobRequest.getCronExpression();
                if (!CronExpression.isValidExpression(cronExpression)) {
                    return CommonResult.failure("cron表达式错误");
                }
            }
            //表达式调度构建器(即任务执行的时间)
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
            scheduleBuilder.withMisfireHandlingInstructionDoNothing();
            //按新的cronExpression表达式构建一个新的trigger
            trigger = TriggerBuilder.newTrigger()
                    .withIdentity(jobClassName, jobGroupName)
                    .withSchedule(scheduleBuilder)

//                .startAt(ben)
//                .endAt(end)
                    .build();
        }

        //构建job信息
        JobDetail jobDetail = JobBuilder.newJob(getInstance(jobClassName).getClass())
                .withIdentity(jobName, jobGroupName)
                .build();
        //测试传递参数，实际使用中根据需要创建参数类，参考https://blog.csdn.net/weixin_30929195/article/details/95012529
        JobParameter jobParameter = new JobParameter();
        jobParameter.setKey1("value1");
        jobParameter.setKey2("value2");
        jobParameter.setKey3("value3");
        trigger.getJobDataMap().put(JobParameter.JOB_PARAM, jobParameter);
        try {

            scheduler.scheduleJob(jobDetail, trigger);
            System.out.println("任务名称：" + jobDetail.getKey().getName());
            System.out.println("分组名称：" + jobDetail.getKey().getGroup());
            System.out.println("任务类：" + jobDetail.getKey().getClass());
            // 启动调度器
            if (!scheduler.isStarted()) {
                scheduler.start();
            }
        } catch (SchedulerException e) {
            throw new Exception("创建定时任务失败" + e);
        }
        return CommonResult.success("创建成功");
    }


    /**
     * 暂停任务
     *
     * @throws Exception
     */
    @PostMapping("/pauseJob")
    public CommonResult<String> pauseJob(@RequestBody JobRequest jobRequest) {

        try {
            String jobName = jobRequest.getJobName();
            String jobGroupName = jobRequest.getJobGroupName();
            JobKey key = new JobKey(jobName, jobGroupName);
            scheduler.pauseJob(key);
            return CommonResult.success("暂停成功");
        } catch (SchedulerException e) {
            e.printStackTrace();
            return CommonResult.failure("暂停失败");
        }
    }

    /**
     * 恢复任务
     *
     * @throws Exception
     */
    @PostMapping("/resumeJob")
    public CommonResult<String> resumeJob(@RequestBody JobRequest jobRequest) {
        try {
            String jobName = jobRequest.getJobName();
            String jobGroupName = jobRequest.getJobGroupName();
            JobKey key = new JobKey(jobName, jobGroupName);
            scheduler.resumeJob(key);
        } catch (SchedulerException e) {
            e.printStackTrace();
            return CommonResult.success("恢复失败");
        }

        return CommonResult.success("恢复任务");
    }

    /**
     * 更新任务
     *
     * @throws Exception
     */
    @PostMapping(value = "rescheduleJob")
    public CommonResult<String> rescheduleJob(@RequestBody JobRequest jobRequest) throws Exception {
        try {
            String jobName = jobRequest.getJobName();
            String cronExpression = jobRequest.getCronExpression();
            String jobGroupName = jobRequest.getJobGroupName();
            TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName);
            if (!CronExpression.isValidExpression(cronExpression)) {
                return CommonResult.failure("cron表达式错误");
            }
            // 表达式调度构建器
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            //测试修改参数
            JobParameter jobParameter = new JobParameter();
//            jobParameter.setKey1("啊");
//            jobParameter.setKey2("哦");
//            jobParameter.setKey3("哈");
            // 按新的cronExpression表达式重新构建trigger
            trigger = trigger.getTriggerBuilder()
                    .withIdentity(triggerKey)
                    .withSchedule(scheduleBuilder)
                    .build();
            //重新设置参数
            trigger.getJobDataMap().put(JobParameter.JOB_PARAM, jobParameter);
            //按新的trigger重新设置job执行
            scheduler.rescheduleJob(triggerKey, trigger);
        } catch (SchedulerException e) {
            throw new Exception("更新定时任务失败" + e);
        }
        return CommonResult.success("更新成功");
    }


    /**
     * 删除任务
     * 删除操作前应该暂停该任务的触发器，并且停止该任务的执行
     *
     * @throws Exception
     */
    @PostMapping(value = "deleteJob")
    public CommonResult<String> deleteJob(@RequestBody JobRequest jobRequest) throws Exception {
        TriggerKey triggerKey = TriggerKey.triggerKey(jobRequest.getJobName(), jobRequest.getJobGroupName());
        scheduler.pauseTrigger(triggerKey);
        scheduler.unscheduleJob(triggerKey);
        scheduler.deleteJob(JobKey.jobKey(jobRequest.getJobName(), jobRequest.getJobGroupName()));
        return CommonResult.success("删除成功");
    }

    /**
     * 查询任务
     *
     * @return
     */
    @PostMapping(value = "queryJob")
    public CommonResult<PageResponseVo<JobVO>> queryJob(PageRequest request) {
        PageResponseDto pageResponseDto = iJobAndTriggerService.pageSearch(BeanCopyUtil.copyProperties(request, PageQueryDto.class));
        return CommonResult.success(BeanCopyUtil.copyPageProperties(pageResponseDto, JobVO.class));
    }

    /**
     * 根据类名称，通过反射得到该类，然后创建一个BaseJob的实例。
     * 由于NewJob和HelloJob都实现了BaseJob，
     * 所以这里不需要我们手动去判断。这里涉及到了一些java多态调用的机制
     *
     * @param classname 类名
     * @return
     * @throws Exception
     */
    public static BaseJob getInstance(String classname) throws Exception {
        Class<?> class1 = Class.forName(classname);
        return (BaseJob) class1.newInstance();
    }

}
